﻿using Ewell.BizComponent.Service.Model.Dto.OutSettlement;
using Ewell.BizComponent.Service.Model.Dto;
using Ewell.BizComponent.Service.Model.Request;
using Ewell.BizComponent.UI.Charge.Model.Request;
using Ewell.BizComponent.UI.Core.VievModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Ewell.Interface.Common.Model.GateWay.Dto.Out;
using Ewell.Interface.Common.Model.GateWay.GateWayUriInfo;
using Ewell.Interface.Common.Utils;
using Ewell.Interface.Common.Model.Common;
using MahApps.Metro.Controls.Dialogs;
using Newtonsoft.Json;
using Ewell.BizComponent.Service.Model.Response;
using Ewell.BizComponent.Service.Server;
using Ewell.BizComponent.UI.Charge.Windows;
using Ewell.BizComponent.UI.Charge.Model.Response;
using System.Windows;
using Ewell.BizComponent.UI.Core.Model;

namespace Ewell.BizComponent.UI.OutSetl.ViewModel
{
    public class OutSettlementVm : ViewModelBase
    {
        /// <summary>
        /// 诊间收费请求
        /// </summary>
        public OutChargeRequest outChargeRequest { get; set; }
        /// <summary>
        /// 预算请求
        /// </summary>
        public OutPreSettlementRequest outPreSettlementRequest { get; set; }
        /// <summary>
        /// 患者
        /// </summary>
        private PatientVm _patient;
        public PatientVm patient
        {
            get => this._patient;
            set
            {
                if (this._patient != value)
                {
                    this._patient = value;
                    this.OnPropertyChanged(nameof(patient));
                }
            }
        }
        /// <summary>
        /// 医保费别
        /// </summary>
        private List<PatientTypeVm> _patientTypeList;
        public List<PatientTypeVm> patientTypeList
        {
            get
            {
                return _patientTypeList;
            }
            set
            {
                if (_patientTypeList != value)
                {
                    _patientTypeList = value;
                    OnPropertyChanged(nameof(patientTypeList));
                }
            }
        }
        /// <summary>
        /// 已选择的医保费别
        /// </summary>
        private PatientTypeVm _selectedPatientType;
        public PatientTypeVm selectedPatientType
        {
            get
            {
                return _selectedPatientType;
            }
            set
            {
                if (_selectedPatientType != value)
                {
                    _selectedPatientType = value;
                    OnPropertyChanged(nameof(selectedPatientType));
                }
            }
        }
        /// <summary>
        /// 处方列表
        /// </summary>
        private List<PrescriptionVm> _prescriptionList;
        public List<PrescriptionVm> prescriptionList
        {
            get => this._prescriptionList;
            set
            {
                if (this._prescriptionList != value)
                {
                    this._prescriptionList = value;
                    this.OnPropertyChanged(nameof(prescriptionList));
                }
            }
        }
        /// <summary>
        /// 收费结果
        /// </summary>
        public OutChargeResponse outChargeResponse { get; set; }

        public Window mainWindow { get; set; }

        public IDialogCoordinator dialogCoordinator { get; set; } = DialogCoordinator.Instance;
        /// <summary>
        /// 加载处方
        /// </summary>
        public ICommand LoadRecipel => new RelayCommand(async (object param) =>
        {
            ProgressDialogController controller = await Application.Current.Dispatcher.Invoke(async () =>
            {
                controller = await dialogCoordinator.ShowProgressAsync(this, "Please wait...", "正在读取收费信息.....!");
                controller.SetIndeterminate();
                return controller;
            });
            
            #region 保存处方
            var orderPresDTOList=await SaveExRecipelAsync();
            #endregion

            #region 查询待缴费处方
            //门诊处方列表
            List<QueryToChargeInfoItemReq> chargeInfoItemReqs = new List<QueryToChargeInfoItemReq>();
            if(orderPresDTOList!=null)
            {
                foreach (var item in orderPresDTOList)
                {
                    QueryToChargeInfoItemReq queryToChargeInfoItemReq = new QueryToChargeInfoItemReq()
                    {
                        presId = item.presId,
                        drugFlag = item.drugFlag,
                    };
                    chargeInfoItemReqs.Add(queryToChargeInfoItemReq);
                }
            }
            //根据条件查询代缴费处方
            QueryToChargeInfoByExampleRequest infoByExampleRequest = new QueryToChargeInfoByExampleRequest()
            {
                queryType = string.IsNullOrWhiteSpace(outChargeRequest.outEncounterId) ? 2 : 1,//查询类型（1-查询有就诊的处方  2-查询无就诊处方）
                outEncounterIds = string.IsNullOrWhiteSpace(outChargeRequest.outEncounterId) ? null : new List<string>() { outChargeRequest.outEncounterId },
                patientId = patient.patientId,
                enabledFlags = new List<string>() { "1" },
                reGetOrderFlag = "0",
                lockFlag = "1",
                presList = chargeInfoItemReqs,
            };
            OutChargeManageDubboService outChargeManageDubboService = new OutChargeManageDubboService();
            var gateWayCharge = outChargeManageDubboService.queryToChargeInfoByExample.Post<QueryToChargeInfoByExampleResponse>(infoByExampleRequest);
            //门诊收费预算
            List<PreSettlementDto> preSettlementDtos = new List<PreSettlementDto>();
            if (!gateWayCharge.success)
            {
                await Application.Current.Dispatcher.BeginInvoke(async () =>
                {
                    await this.dialogCoordinator.ShowMessageAsync(this, "警告!", $"查询代缴费处方失败!");
                });
                if (Global.RuntimeEnv != "System")
                    throw new SpeedException("诊间支付", "未查询到就诊信息!");
            }
            if (gateWayCharge.@object.outEncounterList == null || gateWayCharge.@object.outEncounterList.Count == 0)
            {
                await Application.Current.Dispatcher.BeginInvoke(async () =>
                {
                    await this.dialogCoordinator.ShowMessageAsync(this, "警告!", $"未查询到就诊信息!");
                });
                if (Global.RuntimeEnv != "System")
                    throw new SpeedException("诊间支付", "未查询到就诊信息!");
            }
            if (gateWayCharge.@object.outEncounterList.FirstOrDefault().prescriptionList == null)
            {
                await Application.Current.Dispatcher.BeginInvoke(async () =>
                {
                    await this.dialogCoordinator.ShowMessageAsync(this, "警告!", $"未查询到代缴费处方!");
                });
                if (Global.RuntimeEnv != "System")
                    throw new SpeedException("诊间支付", "未查询到代缴费处方!");
            }
            var prescriptions = new List<PrescriptionVm>();
            foreach (var item in gateWayCharge.@object.outEncounterList)
            {
                var preList = JsonConvert.DeserializeObject<List<PrescriptionVm>>(JsonConvert.SerializeObject(item.prescriptionList));
                if(preList!=null&& preList.Count>0)
                    prescriptions.AddRange(preList);
                List<BillItemDto> billItemDtos = new List<BillItemDto>();
                foreach (var prescription in item.prescriptionList)
                {
                    BillItemDto billItem = new BillItemDto();
                    billItem.billItemId = GuidHelper.GenerateUnique19DigitId().ToString();
                    billItem.isDrug = prescription.drugFlag;
                    billItem.herbNumber = prescription.herbalTieCount;
                    billItem.presByDocId = prescription.prescribedDoctorId;
                    billItem.presByDeptId = prescription.prescribedDeptId;
                    billItem.execDeptId = prescription.execDeptId;
                    billItem.presId = prescription.presId;
                    billItem.presedAt = prescription.presAt;
                    var commodityDtos = new List<Service.Model.CommodityDto>();
                    List<OrderDetailDto> orderDetailDtos = new List<OrderDetailDto>();
                    foreach (var orderDetail in prescription.orderDetailList)
                    {
                        OrderDetailDto orderDetailDto = new OrderDetailDto()
                        {
                            orderDetailId = orderDetail.orderDetailId,
                            orderDetailTypeCoding = orderDetail.orderDetailTypeCoding,
                            orderItemId = orderDetail.orderItemId,
                            orderItemName = orderDetail.orderItemName,
                            presDetailIds = orderDetail.presDetails.Select(s => s.presDetailId).ToList(),
                            quantityCharged = orderDetail.quanlity,
                        };
                        orderDetailDtos.Add(orderDetailDto);
                        foreach (var presDetail in orderDetail.presDetails)
                        {
                            Service.Model.CommodityDto commodityDto = new Service.Model.CommodityDto()
                            {
                                commodityId = presDetail.commodityID,
                                commoditySpec = presDetail.commoditySpec,
                                medicareCheckStatus = presDetail.medicareCheckStatus,
                                amount = presDetail.originalPrice,
                                payAmount = presDetail.payAmount,
                                clinicOrderDetailId = orderDetail.orderDetailId,
                                commodityName = presDetail.commodityName,
                                commodityPrice = presDetail.originalPrice,
                                commodityQuantity = presDetail.quatityPres,
                                commodityTypeCoding = presDetail.commodityTypeCode,
                                commodityUnitName = presDetail.unitName,
                                retailUnitFactor = presDetail.retailUnitFactor,
                                insurMinUploadFlag = presDetail.insurMinUploadFlag,
                                needUploadFlag = presDetail.needUploadFlag,
                                retailPrice = presDetail.itemPrice,
                                tcmDrugUsedWay = presDetail.tcmDrugUsedWayCoding,
                                presDetailId = presDetail.presDetailId,
                            };
                            commodityDtos.Add(commodityDto);
                        }
                    }
                    billItem.commodityList = commodityDtos;

                    billItem.orderDetailList = orderDetailDtos;
                    billItemDtos.Add(billItem);
                }
                await Application.Current.Dispatcher.BeginInvoke(async () =>
                {
                    this.prescriptionList = prescriptions;
                });
                PreSettlementDto preSettlementDto = new PreSettlementDto()
                {
                    outEncounterId = outChargeRequest.outEncounterId,
                    insurTypeId = selectedPatientType.no,
                    paymentTypeCoding = "1",
                    billItemList = billItemDtos,
                };
                preSettlementDtos.Add(preSettlementDto);
            }
            this.outPreSettlementRequest = new OutPreSettlementRequest()
            {
                bizSourceCoding = outChargeRequest.bizSourceCode,
                menuId = outChargeRequest.menuId,
                encounter = new EncounterDto() { encounterId = long.Parse(outChargeRequest.outEncounterId) },
                patient = new PatientDto() { insurTypeId = patient.patientTypeNo, patientId = patient.patientId, patientName = patient.name },
                preSettlementList = preSettlementDtos,
                settlementTypeCode = "2",
            };
            #endregion

            await Application.Current.Dispatcher.BeginInvoke(async () =>
            {
                controller.SetCancelable(true);
                await controller.CloseAsync();
            });
            
            //收费
            //if (Global.RuntimeEnv != "System"&& outChargeRequest != null && outChargeRequest.presList != null)
            //    Settlement.Execute(param);
        });
        /// <summary>
        /// 收费
        /// </summary>
        public ICommand Settlement => new RelayCommand(async (object param) =>
        {
            try
            {
                ChargeWindow chargeWindow = new ChargeWindow()
                {
                    chargeVm = new Charge.ViewModel.ChargeVm()
                    {
                        preSettlementVm = new Charge.ViewModel.PreSettlementVm()
                        {
                            outPreSettlementRequest = this.outPreSettlementRequest,
                            selectedPatientType = selectedPatientType,
                            patient = patient,
                        },
                        patientVm = patient,
                    },
                };
                chargeWindow.ShowDialog();
                outChargeResponse = chargeWindow?.chargeVm?.settlementVm?.outChargeResponse;
                if (outChargeResponse==null||string.IsNullOrWhiteSpace(outChargeResponse.outEncountId))
                {
                    return;
                }
                await this.dialogCoordinator.ShowMessageAsync(this, "成功", $"收费成功!");
                if(Global.RuntimeEnv!= "System")
                    this.mainWindow?.Close();
            }
            catch (Exception ex)
            {
                if (Global.RuntimeEnv == "System")
                    await this.dialogCoordinator.ShowMessageAsync(this, "警告", $"收费失败!,{ex.Message}");
                else
                    throw new SpeedException("HISBIZ", $"收费失败!,{ex.Message}");
            }
        });

        public ICommand Cancel => new RelayCommand((object param) =>
        {
            if (Global.RuntimeEnv == "System")
                this.mainWindow?.Close();
            else
                throw new SpeedException("HISBIZ", "用户取消了操作!");
        });

        private async Task<List<SaveOrderPresDTO>> SaveExRecipelAsync()
        {
            if (outChargeRequest != null && outChargeRequest.presList != null)
            {
                //保存外部医嘱
                //诊断列表
                List<SaveExClinicalOrderDisgnosisDTO> saveExClinicalOrders = new List<SaveExClinicalOrderDisgnosisDTO>();
                if (outChargeRequest.diagnosisList != null)
                    foreach (var item in outChargeRequest.diagnosisList)
                    {
                        SaveExClinicalOrderDisgnosisDTO saveExClinicalOrderDisgnosisDTO = new SaveExClinicalOrderDisgnosisDTO()
                        {
                            diagnosisCode = item.diagnosisCode,
                            diagnosisName = item.diagnosisName,
                            disgnosisFid = item.disgnosisFid,
                            mainDiagFlag = item.mainDiagFlag,
                        };
                        saveExClinicalOrders.Add(saveExClinicalOrderDisgnosisDTO);
                    }
                //处方列表
                List<SaveExClinicalOrderPresDTO> saveExClinicalOrderPres = new List<SaveExClinicalOrderPresDTO>();
                if (outChargeRequest.presList != null)
                    foreach (var item in outChargeRequest.presList)
                    {
                        List<SaveExClinicalOrderDisgnosisDTO> saveExClinicalOrderDisgnoses = new List<SaveExClinicalOrderDisgnosisDTO>();
                        if (item.diagnosisList != null)
                            foreach (var orderDisg in item.diagnosisList)
                            {
                                SaveExClinicalOrderDisgnosisDTO saveEx = new SaveExClinicalOrderDisgnosisDTO()
                                {
                                    diagnosisCode = orderDisg.diagnosisCode,
                                    diagnosisName = orderDisg.diagnosisName,
                                    disgnosisFid = orderDisg.disgnosisFid,
                                    mainDiagFlag = orderDisg.mainDiagFlag,
                                };
                                saveExClinicalOrderDisgnoses.Add(saveEx);
                            }
                        List<SaveExClinicalOrderDetailDTO> saveExClinicals = new List<SaveExClinicalOrderDetailDTO>();
                        foreach (var orderDetai in item.orderDetailList)
                        {
                            List<SaveExClinicalChargeDetailDTO> chargeDetailDTOs = new List<SaveExClinicalChargeDetailDTO>();
                            foreach (var chargeDetai in orderDetai.chargeDetailList)
                            {
                                SaveExClinicalChargeDetailDTO detailDTO = new SaveExClinicalChargeDetailDTO()
                                {
                                    medicareCheckStatus = chargeDetai.medicareCheckStatus,
                                    babyAddFlag = chargeDetai.babyAddFlag,
                                    chargeDetailFid = chargeDetai.chargeDetailFid,
                                    commodityCode = chargeDetai.commodityCode,
                                    commodityFid = chargeDetai.commodityFid,
                                    commodityName = chargeDetai.commodityName,
                                    commodityTypeCoding = chargeDetai.drugFlag == "1" ? chargeDetai.drugFlag : "2",
                                    herbUsedWay = chargeDetai.herbUsedWay,
                                    needUploadFlag = chargeDetai.needUploadFlag,
                                    retailAmount = chargeDetai.retailAmount,
                                    retailPrice = chargeDetai.retailPrice,
                                    retailQuantity = chargeDetai.retailQuantity,
                                    retailUnitDesc = chargeDetai.retailUnitDesc,
                                    retailUnitFactor = chargeDetai.retailUnitFactor,
                                    insurMinUploadFlag = chargeDetai.insurMinUploadFlag,
                                };
                                chargeDetailDTOs.Add(detailDTO);
                            }
                            SaveExClinicalOrderDetailDTO saveExClinicalOrderDetailDTO = new SaveExClinicalOrderDetailDTO()
                            {
                                orderDetailFid = orderDetai.orderDetailFid,
                                orderItemCode = orderDetai.orderItemCode,
                                orderItemFid = orderDetai.orderItemFid,
                                orderItemName = orderDetai.orderItemName,
                                retailQuantity = orderDetai.retailQuantity,
                                chargeDetailList = chargeDetailDTOs,
                            };
                            saveExClinicals.Add(saveExClinicalOrderDetailDTO);
                        }
                        List<SaveExClinicalOrderMedicareDiseaseDTO> saveExClinicalOrderMedicares = new List<SaveExClinicalOrderMedicareDiseaseDTO>();
                        if (item.medicareDiseaseList != null)
                            foreach (var medicareDisease in item.medicareDiseaseList)
                            {
                                SaveExClinicalOrderMedicareDiseaseDTO saveExClinicalOrderMedicare = new SaveExClinicalOrderMedicareDiseaseDTO()
                                {
                                    medicareDiseaseId = medicareDisease.medicareDiseaseId,
                                    medicareDiseaseName = medicareDisease.medicareDiseaseName,
                                };
                                saveExClinicalOrderMedicares.Add(saveExClinicalOrderMedicare);
                            }
                        SaveExClinicalOrderPresDTO saveExClinicalOrderPresDTO = new SaveExClinicalOrderPresDTO()
                        {
                            chargeGroupNo = item.chargeGroupNo ?? "0",
                            bizSourceCoding = item.bizSourceCoding,
                            zoneCode = item.zoneCode,
                            elecRequisitionNo = item.elecRequisitionNo,
                            executdByDeptCode = item.executdByDeptCode,
                            executdByDeptFid = item.executdByDeptFid,
                            herbTieNumber = item.herbTieNumber,
                            medicareTyeCoding = item.medicareTyeCoding,
                            presedAt = item.presedAt,
                            presedByDeptCode = item.presedByDeptCode,
                            executUnitCategCoding = item.executUnitCategCoding,
                            presedByDeptFid = item.presedByDeptFid,
                            presedByUserCode = item.presedByUserCode,
                            presedByUserFid = item.presedByUserFid,
                            presExpiredAt = item.presExpiredAt,
                            presFid = item.presFid,
                            diagnosticFeeFlag=item.diagnosticFeeFlag,
                            presNo = item.presNo,
                            presTypeCoding = item.presTypeCoding,
                            priortyFlag = item.priortyFlag,
                            retailAmount = item.retailAmount,
                            diagnosisList = saveExClinicalOrderDisgnoses,
                            orderDetailList = saveExClinicals,
                            medicareDiseaseList = saveExClinicalOrderMedicares,
                        };
                        saveExClinicalOrderPres.Add(saveExClinicalOrderPresDTO);
                    }
                SaveExClinicalOrderRequest saveExClinicalOrder = new SaveExClinicalOrderRequest()
                {
                    outEncounterList = new List<SaveExClinicalOrderEncounter>()
                    {
                        new SaveExClinicalOrderEncounter()
                        {
                            outEncounterId=outChargeRequest.outEncounterId,
                            diagnosisList=saveExClinicalOrders,
                            presList=saveExClinicalOrderPres,
                        }
                    }
                };
                ClinicalOrderManageDubboService clinicalOrderManageDubboService = new ClinicalOrderManageDubboService();
                var gateWayOrder = clinicalOrderManageDubboService.saveExClinicalOrder.Post<SaveExClinicalOrderResponse>(saveExClinicalOrder);
                if (!gateWayOrder.success)
                {
                    await Application.Current.Dispatcher.BeginInvoke(async () =>
                    {
                        await this.dialogCoordinator.ShowMessageAsync(this, "警告!", $"拉取处方信息失败!");
                    });
                    throw new SpeedException("诊间支付", "拉取处方信息失败!");
                }
                if(gateWayOrder.hasWarning)
                {
                    await Application.Current.Dispatcher.BeginInvoke(async () =>
                    {
                        await this.dialogCoordinator.ShowMessageAsync(this, "警告!", $"{gateWayOrder.message}");
                    });
                }
                if (gateWayOrder.@object.presList != null)
                    return gateWayOrder.@object.presList;
            }
            return null;
        }
    }
}
